namespace Creek.UI.Tabstrip.Helpers
{
    using System.Collections;
    using System.ComponentModel;

    /// <summary>
    /// 	Represents the method that will handle the event that has no data.
    /// </summary>
    public delegate void CollectionClear();

    /// <summary>
    /// 	Represents the method that will handle the event that has item data.
    /// </summary>
    public delegate void CollectionChange(int index, object value);

    /// <summary>
    /// 	Extend collection base class by generating change events.
    /// </summary>
    public abstract class CollectionWithEvents : CollectionBase
    {
        // Instance fields
        private int _suspendCount;

        /// <summary>
        /// 	Initializes DrawTab new instance of the CollectionWithEvents class.
        /// </summary>
        public CollectionWithEvents()
        {
            // Default to not suspended
            this._suspendCount = 0;
        }

        /// <summary>
        /// 	Gets DrawTab value indicating if events are currently suspended.
        /// </summary>
        [Browsable(false)]
        public bool IsSuspended
        {
            get
            {
                return (this._suspendCount > 0);
            }
        }

        /// <summary>
        /// 	Occurs just before the collection contents are cleared.
        /// </summary>
        [Browsable(false)]
        public event CollectionClear Clearing;

        /// <summary>
        /// 	Occurs just after the collection contents are cleared.
        /// </summary>
        [Browsable(false)]
        public event CollectionClear Cleared;

        /// <summary>
        /// 	Occurs just before an item is added to the collection.
        /// </summary>
        [Browsable(false)]
        public event CollectionChange Inserting;

        /// <summary>
        /// 	Occurs just after an item has been added to the collection.
        /// </summary>
        [Browsable(false)]
        public event CollectionChange Inserted;

        /// <summary>
        /// 	Occurs just before an item is removed from the collection.
        /// </summary>
        [Browsable(false)]
        public event CollectionChange Removing;

        /// <summary>
        /// 	Occurs just after an item has been removed from the collection.
        /// </summary>
        [Browsable(false)]
        public event CollectionChange Removed;

        /// <summary>
        /// 	Do not generate change events until resumed.
        /// </summary>
        public void SuspendEvents()
        {
            this._suspendCount++;
        }

        /// <summary>
        /// 	Safe to resume change events.
        /// </summary>
        public void ResumeEvents()
        {
            --this._suspendCount;
        }

        /// <summary>
        /// 	Raises the Clearing event when not suspended.
        /// </summary>
        protected override void OnClear()
        {
            if (!this.IsSuspended)
            {
                // Any attached event handlers?
                if (this.Clearing != null)
                {
                    this.Clearing();
                }
            }
        }

        /// <summary>
        /// 	Raises the Cleared event when not suspended.
        /// </summary>
        protected override void OnClearComplete()
        {
            if (!this.IsSuspended)
            {
                // Any attached event handlers?
                if (this.Cleared != null)
                {
                    this.Cleared();
                }
            }
        }

        /// <summary>
        /// 	Raises the Inserting event when not suspended.
        /// </summary>
        /// <param name="index"> Index of object being inserted. </param>
        /// <param name="value"> The object that is being inserted. </param>
        protected override void OnInsert(int index, object value)
        {
            if (!this.IsSuspended)
            {
                // Any attached event handlers?
                if (this.Inserting != null)
                {
                    this.Inserting(index, value);
                }
            }
        }

        /// <summary>
        /// 	Raises the Inserted event when not suspended.
        /// </summary>
        /// <param name="index"> Index of inserted object. </param>
        /// <param name="value"> The object that has been inserted. </param>
        protected override void OnInsertComplete(int index, object value)
        {
            if (!this.IsSuspended)
            {
                // Any attached event handlers?
                if (this.Inserted != null)
                {
                    this.Inserted(index, value);
                }
            }
        }

        /// <summary>
        /// 	Raises the Removing event when not suspended.
        /// </summary>
        /// <param name="index"> Index of object being removed. </param>
        /// <param name="value"> The object that is being removed. </param>
        protected override void OnRemove(int index, object value)
        {
            if (!this.IsSuspended)
            {
                // Any attached event handlers?
                if (this.Removing != null)
                {
                    this.Removing(index, value);
                }
            }
        }

        /// <summary>
        /// 	Raises the Removed event when not suspended.
        /// </summary>
        /// <param name="index"> Index of removed object. </param>
        /// <param name="value"> The object that has been removed. </param>
        protected override void OnRemoveComplete(int index, object value)
        {
            if (!this.IsSuspended)
            {
                // Any attached event handlers?
                if (this.Removed != null)
                {
                    this.Removed(index, value);
                }
            }
        }

        /// <summary>
        /// 	Returns the index of the first occurrence of DrawTab value.
        /// </summary>
        /// <param name="value"> The object to locate. </param>
        /// <returns> Index of object; otherwise -1 </returns>
        protected int IndexOf(object value)
        {
            // Find the 0 based index of the requested entry
            return this.List.IndexOf(value);
        }
    }
}